package com.spzx.product.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.domain.SkuLockVo;
import com.spzx.product.domain.SkuStock;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.SkuStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * BelongProject: spzx-parent
 * BelongPackage: com.spzx.product.service.impl
 * Description:
 *
 * @Author 段鑫涛
 * @Create 2025/6/7 0:18
 * @Version 1.0
 */
@Service
public class SkuStockServiceImpl extends ServiceImpl<SkuStockMapper, SkuStock> implements SkuStockService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SkuStockMapper skuStockMapper;

    @Override
    public String checkAndLockStock(String orderNo, List<SkuLockVo> skuLockVoList) {

        String stockLockKey = "sku:checkAndLock:" + orderNo;// 分布式锁，防止表单重复提交的
        String stockDataKey = "sku:lock:data:" + orderNo;// 将来解锁或者扣减库存的时候方便获取当初锁定的库存信息

        Boolean isExist = redisTemplate.opsForValue().setIfAbsent(stockLockKey, orderNo, 30, TimeUnit.MINUTES);
        if (!isExist) {
            //如果存在，则已执行过库存锁定
            if(redisTemplate.hasKey(stockDataKey)) {
                return "";
            } else {
                return "重复提交";
            }
        }

        // 遍历所有商品，验库存并锁库存，要具备原子性
        skuLockVoList.forEach(skuLockVo -> {
            // 验库存：查询，返回的是满足要求的库存列表
            SkuStock skuStock = skuStockMapper.check(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
            // 如果没有一个商品满足要求，这里就验库存失败
            if (null == skuStock) {
                //没有库存
                skuLockVo.setIsHaveStock(false);
            } else {
                //有库存
                skuLockVo.setIsHaveStock(true);
            }
        });

        // 只要有一个商品锁定失败，所有锁定成功的商品要解锁库存
        if (skuLockVoList.stream().anyMatch(skuLockVo -> !skuLockVo.getIsHaveStock())) {
            // 获取所有锁定成功的商品，遍历解锁库存
            StringBuffer result = new StringBuffer();
            //获取没有库存的对象列表
            List<SkuLockVo> noHaveStockSkuLockVoList = skuLockVoList.stream().filter(item -> !item.getIsHaveStock()).collect(Collectors.toList());
            for(SkuLockVo noHaveStockSkuLockVo : noHaveStockSkuLockVoList) {
                //解除去重
                this.redisTemplate.delete(stockLockKey);
                result.append("商品: " + noHaveStockSkuLockVo.getSkuId() + " 库存不足; ");
            }
            //锁定失败，解除
            redisTemplate.delete(stockLockKey);
            // 响应锁定状态
            return result.toString();
        } else {
            //锁定库存
            skuLockVoList.forEach(skuLockVo -> {
                int row = skuStockMapper.lock(skuLockVo.getSkuId(), skuLockVo.getSkuNum());
                if(row == 0) {
                    //解除去重
                    this.redisTemplate.delete(stockLockKey);
                    throw new ServiceException("库存锁定失败");
                }
            });
        }

        // 如果所有商品都锁定成功的情况下，需要缓存锁定信息到redis。以方便将来解锁库存 或者 减库存
        this.redisTemplate.opsForValue().set(stockDataKey, skuLockVoList);
        return "";

    }
}
